package cn.signalpha.modules.shop.controller.admin;

import cn.signalpha.common.constant.AppConstant;
import cn.signalpha.common.dto.IdDTO;
import cn.signalpha.core.boot.ctrl.BaseController;
import cn.signalpha.core.excel.util.ExcelMergeRowUtil;
import cn.signalpha.core.excel.util.ExcelUtil;
import cn.signalpha.core.mp.support.Condition;
import cn.signalpha.core.mp.support.Query;
import cn.signalpha.core.tool.api.R;
import cn.signalpha.core.tool.support.Kv;
import cn.signalpha.core.tool.utils.BeanUtil;
import cn.signalpha.core.tool.utils.DateUtil;
import cn.signalpha.core.tool.utils.Func;
import cn.signalpha.core.tool.utils.StringPool;
import cn.signalpha.modules.shop.dto.OrderDTO;
import cn.signalpha.modules.shop.dto.OrderLogisticsBatchDTO;
import cn.signalpha.modules.shop.dto.OrderLogisticsDTO;
import cn.signalpha.modules.shop.dto.OrderRefundDTO;
import cn.signalpha.modules.shop.entity.Order;
import cn.signalpha.modules.shop.excel.OrderExcel;
import cn.signalpha.modules.shop.excel.OrderInputExcel;
import cn.signalpha.modules.shop.service.*;
import cn.signalpha.modules.shop.vo.OrderVO;
import cn.signalpha.modules.shop.wrapper.OrderWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;


@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_SHOP_NAME + "/admin/order")
@Api(value = "订单", tags = "订单")
public class OrderController extends BaseController {

	private final OrderService orderService;
	private final OrderDetailService orderDetailService;
	private final OrderSettleService orderSettleService;
	private final OrderRefundService orderRefundService;
	private final OrderLogisticsService orderLogisticsService;
	private final OrderLogisticsDetailService orderLogisticsDetailService;

	@GetMapping("/page")
	@ApiImplicitParams({
		@ApiImplicitParam(name="userId", dataType = "string", value = "用户id"),
		@ApiImplicitParam(name="sellerId", dataType = "string", value = "商户id"),
		@ApiImplicitParam(name="orderNo", dataType = "string", value = "订单号"),
		@ApiImplicitParam(name="payStatus", dataType = "string", value = "支付状态"),
		@ApiImplicitParam(name="orderStatus", dataType = "string", value = "订单状态"),
		@ApiImplicitParam(name="orderType", dataType = "string", value = "订单类型"),
		@ApiImplicitParam(name="logisticsType", dataType = "string", value = "物流方式"),
		@ApiImplicitParam(name="goodsName", dataType = "string", value = "商品名称"),
		@ApiImplicitParam(name="createTimeBegin", dataType = "string", value = "开始时间"),
		@ApiImplicitParam(name="createTimeEnd", dataType = "string", value = "结束时间"),
	})
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "分页", notes = "传入order")
	public R<IPage<OrderVO>> page(@ApiIgnore @RequestParam Map<String, Object> params, Query query) {
		QueryWrapper<Order> wrapper = orderService.selectOrderWrapper(params);
		IPage<Order> page = orderService.page(Condition.getPage(query), wrapper);
		return R.data(OrderWrapper.build().pageVO(page));
	}

	@GetMapping("/status")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "状态统计", notes = "传入order")
	public R<Map<String, Object>> countStatus(@ApiIgnore @RequestParam Map<String, Object> params) {
		Map<String, Object> map = new HashMap<>();
		map.put("data_1", orderService.countByParams(Kv.create().setAll(params).set("orderStatus", "-1")));
		map.put("data", orderService.countByParams(Kv.create().setAll(params)));
		map.put("data0", orderService.countByParams(Kv.create().setAll(params).set("orderStatus", "0")));
		map.put("data1", orderService.countByParams(Kv.create().setAll(params).set("orderStatus", "1")));
		map.put("data2", orderService.countByParams(Kv.create().setAll(params).set("orderStatus", "2")));
		map.put("data3", orderService.countByParams(Kv.create().setAll(params).set("orderStatus", "3")));
		return R.data(map);
	}

	@GetMapping("/goods/price/total")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "商品金额统计", notes = "传入order")
	public R goodsPriceTotal(@ApiIgnore @RequestParam Map<String, Object> params) {
		return R.data(orderService.sumByParams(params, "goods_price"));
	}

	@GetMapping("/order/price/total")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "订单金额统计", notes = "传入order")
	public R orderPriceTotal(@ApiIgnore @RequestParam Map<String, Object> params) {
		return R.data(orderService.sumByParams(params, "order_price"));
	}

	@GetMapping("/excel")
	@ApiOperation(value = "导出excel", notes = "")
	public void excel(@ApiIgnore @RequestParam Map<String, Object> params, HttpServletResponse response) {
		QueryWrapper<Order> wrapper = orderService.selectOrderWrapper(params);
		List<OrderVO> orderList = OrderWrapper.build().listVO(orderService.list(wrapper));
		List<OrderExcel> orderExcelList = new ArrayList<>();
		orderList.forEach(orderVO -> orderVO.getOrderDetailList().forEach(orderDetail -> {
			OrderExcel orderExcel = Objects.requireNonNull(BeanUtil.copy(orderVO, OrderExcel.class));
			//商品信息
			orderExcel.setGoodsName(orderDetail.getGoods().getName());
			orderExcel.setGoodsSpec(orderDetail.getGoods().getGoodsSpec());
			orderExcel.setGoodsUnitPrice(orderDetail.getGoods().getGoodsPrice());
			orderExcel.setGoodsTotalPrice(orderDetail.getGoods().getGoodsPriceTotal());
			//收货信息
			orderExcel.setProvince(orderVO.getLogistics().getProvince());
			orderExcel.setCity(orderVO.getLogistics().getCity());
			orderExcel.setDistrict(orderVO.getLogistics().getDistrict());
			orderExcel.setAddress(orderVO.getLogistics().getAddress());
			orderExcel.setConsignee(orderVO.getLogistics().getConsignee());
			orderExcel.setMobile(orderVO.getLogistics().getMobile());
			orderExcelList.add(orderExcel);
		}));

		//需要合并的列
		int[] mergeColumnIndex = {0,1,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29};
		ExcelMergeRowUtil excelMergeRowUtil = new ExcelMergeRowUtil(mergeColumnIndex, orderExcelList.size());
		ExcelUtil.export(response, DateUtil.time(), StringPool.EMPTY, orderExcelList, excelMergeRowUtil, OrderExcel.class);
	}

	@GetMapping("/info")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "详情", notes = "传入id")
	public R<OrderVO> info(@RequestParam String id) {
		return R.data(OrderWrapper.build().entityVO(orderService.getById(id)));
	}

	@PostMapping("/remove")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "删除订单", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		orderService.listByIds(Func.toLongList(ids)).forEach(order -> {
			orderService.removeById(order.getId());
			orderDetailService.removeByOrderNo(order.getOrderNo());
			orderSettleService.removeByOrderNo(order.getOrderNo());
			orderLogisticsService.removeByOrderNo(order.getOrderNo());
			orderLogisticsDetailService.removeByOrderNo(order.getOrderNo());
		});
		return R.status(true);
	}

	@PostMapping("/update/address")
	@ApiOperationSupport(order = 21)
	@ApiOperation(value = "修改地址", notes = "")
	public R updateAddress(@Valid @RequestBody OrderDTO.UpdateUserAddressDTO orderDTO) {
		return R.status(orderService.updateUserAddress(orderDTO.getId(), orderDTO.getAddressId()));
	}

	@PostMapping("/logistics/save")
	@ApiOperationSupport(order = 30)
	@ApiOperation(value = "发货备货", notes = "")
	public R logisticsSave(@Valid @RequestBody OrderLogisticsDTO orderLogisticsDTO){
		return R.status(orderService.logisticsSave(orderLogisticsDTO));
	}

	@PostMapping("/logistics/batch/save")
	@ApiOperationSupport(order = 31)
	@ApiOperation(value = "批量发货备货", notes = "")
	public R logisticsBatchSave(@Valid @RequestBody OrderLogisticsBatchDTO orderLogisticsBatchDTO){
		Func.toLongList(orderLogisticsBatchDTO.getOrderId()).forEach(orderId -> {
			OrderLogisticsDTO orderLogisticsDTO = new OrderLogisticsDTO();
			orderLogisticsDTO.setType(1);
			orderLogisticsDTO.setOrderId(orderId);
			orderLogisticsDTO.setLogisticsNo(orderLogisticsBatchDTO.getLogisticsNo());
			orderService.logisticsSave(orderLogisticsDTO);
		});
		return R.status(true);
	}

	@PostMapping("/remark")
	@ApiOperationSupport(order = 32)
	@ApiOperation(value = "备注订单", notes = "")
	public R remark(@Valid @RequestBody OrderDTO.RemarkDTO remarkDTO){
		return R.status(orderService.updateById(BeanUtil.copy(remarkDTO, Order.class)));
	}

	@PostMapping("/logistics/import")
	@ApiOperationSupport(order = 32)
	@ApiOperation(value = "发货导入", notes = "")
	public R logisticsExcelInput(@RequestParam("file") MultipartFile multipartFile) {
		return R.status(orderService.shippingImport(ExcelUtil.read(multipartFile, OrderInputExcel.class)));
	}

	@GetMapping("/logistics/template")
	@ApiOperationSupport(order = 33)
	@ApiOperation(value = "发货导入模版", notes = "")
	public void logisticsExcelTemplate(HttpServletResponse response) {
		ExcelUtil.export(response, "订单导入模板", "订单导入表", new ArrayList<>(), OrderInputExcel.class);
	}

	@PostMapping("/finish")
	@ApiOperationSupport(order = 50)
	@ApiOperation(value = "完成订单", notes = "")
	public R finish(@Valid @RequestBody IdDTO idDTO){
		return R.status(orderService.receiptOrder(idDTO.getId()));
	}

	@PostMapping("/refund")
	@ApiOperationSupport(order = 60)
	@ApiOperation(value = "退款订单", notes = "")
	public R refund(@Valid @RequestBody OrderDTO.RefundDTO refundDTO){
		refundDTO.getDetailList().forEach(refundDetailDTO -> {
			OrderRefundDTO.ApplyDTO applyDTO = new OrderRefundDTO.ApplyDTO();
			applyDTO.setOrderId(refundDTO.getId());
			applyDTO.setOrderDetailId(refundDetailDTO.getOrderDetailId());
			applyDTO.setGoodsNum(refundDetailDTO.getGoodsNum());
			applyDTO.setGoodsStatus(0);
			applyDTO.setRefundType(1);
			Long refundId = orderRefundService.buyerApply(applyDTO, false);
			orderRefundService.sellerAgreeShipping(refundId);
		});
		return R.status(true);
	}

}
